home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagn_r.zip / NUMBERS.SWG / 0042_Setting Bit Flags in ASM.pas < prev    next >
Pascal/Delphi Source File  |  1994-02-09  |  8KB  |  329 lines

  1. (*
  2. Date:   02-05-95
  3. From:   DON PAULSEN
  4.  
  5.  
  6.         This unit provides routines to manipulate individual bits
  7.         in memory, including test, set, clear, and toggle.  You may
  8.         also count the number of bits set with NumFlagsSet, and get
  9.         a "picture" of them with the function FlagString.
  10.  
  11.         All the routines are in the interface section to provide
  12.         complete low-level control of your own data space used for
  13.         flags.  Usually the oFlags object will be most convenient.
  14.         Just initialize the object with the number of flags required,
  15.         and it will allocate sufficient memory on the heap and clear
  16.         them to zero.
  17. *)
  18.  
  19.  
  20. UNIT DpFlags;
  21.  
  22. {$A+,B-,D-,E-,F-,G-,I-,L-,N-,O-,R-,S-,V-,X-}
  23. {$IFDEF VER70} {$P-,Q-,T-,Y-} {$ENDIF}
  24.  
  25. (*
  26.     File(s)         DPFLAGS.PAS
  27.     Unit(s)         None
  28.     Compiler        Turbo Pascal v6.0+
  29.     Author          Don Paulsen
  30.     v1.00 Date       7-01-92
  31.     Last Change     11-12-93
  32.     Version         1.11
  33. *)
  34.  
  35. { Flags are numbered from left to right (low memory to high memory),
  36.   starting with 0, to a maximum of 65520.  If the flags object isn't used,
  37.   use the System.FillChar routine to set or clear all the flags at once.
  38.   The memory for storing the flags can be allocated in the data segment
  39.   or on the heap.
  40.  
  41.   Here are two methods for declaring an array for the flags (not needed if
  42.   the oFlags object is used):
  43.  
  44.     CONST
  45.        cMaxFlagNumber = 50;
  46.        cNumberOfFlags = 51;
  47.  
  48.     VAR
  49.        flags_A : array [0..(cMaxFlagNumber div 8)] of byte;
  50.        flags_B : array [0..(cNumberOfFlags - 1) div 8] of byte;
  51.  
  52.   Note that since the first flag is flag 0, cNumberOfFlags is always 1 greater
  53.   than cMaxFlagNumber. }
  54.  
  55.  
  56. INTERFACE
  57.  
  58. PROCEDURE SetFlag     (var flags; flagNum : word);
  59. PROCEDURE ClearFlag   (var flags; flagNum : word);
  60. PROCEDURE ToggleFlag  (var flags; flagNum : word);
  61. FUNCTION  FlagIsSet   (var flags; flagNum : word): boolean;
  62. FUNCTION  NumFlagsSet (var flags; numFlags: word): word;
  63. FUNCTION  FlagString  (var flags; numFlags: word): string;
  64.  
  65. TYPE
  66.     tFlags = ^oFlags;
  67.     oFlags = OBJECT
  68.                CONSTRUCTOR Init (numberOfFlags: word);
  69.                PROCEDURE   ClearAllFlags;
  70.                PROCEDURE   SetAllFlags;
  71.                PROCEDURE   SetFlag    (flagNum: word);
  72.                PROCEDURE   ClearFlag  (flagNum: word);
  73.                PROCEDURE   ToggleFlag (flagNum: word);
  74.                FUNCTION    FlagIsSet  (flagNum: word): boolean;
  75.                FUNCTION    NumFlagsSet : word;
  76.                FUNCTION    FlagString  : string;
  77.                DESTRUCTOR  Done;
  78.              PRIVATE
  79.                 flags    : pointer;
  80.                 numFlags : word;
  81.              END;
  82.  
  83.  
  84. IMPLEMENTATION
  85.  
  86. {=======================================================}
  87. PROCEDURE SetFlag (var flags; flagNum: word); assembler;
  88.  
  89. ASM
  90.     les     di, flags
  91.     mov     cx, flagNum
  92.     mov     bx, cx
  93.     shr     bx, 1
  94.     shr     bx, 1
  95.     shr     bx, 1
  96.     and     cl, 7
  97.     mov     al, 80h
  98.     shr     al, cl
  99.     or      es:[di][bx], al
  100. END;
  101.  
  102. {=========================================================}
  103. PROCEDURE ClearFlag (var flags; flagNum: word); assembler;
  104.  
  105. ASM
  106.     les     di, flags
  107.     mov     cx, flagNum
  108.     mov     bx, cx
  109.     shr     bx, 1
  110.     shr     bx, 1
  111.     shr     bx, 1
  112.     and     cl, 7
  113.     mov     al, 7Fh
  114.     ror     al, cl
  115.     and     es:[di][bx], al
  116. END;
  117.  
  118. {==========================================================}
  119. PROCEDURE ToggleFlag (var flags; flagNum: word); assembler;
  120.  
  121. ASM
  122.     les     di, flags
  123.     mov     cx, flagNum
  124.     mov     bx, cx
  125.     shr     bx, 1
  126.     shr     bx, 1
  127.     shr     bx, 1
  128.     and     cl, 7
  129.     mov     al, 80h
  130.     shr     al, cl
  131.     xor     es:[di][bx], al
  132. END;
  133.  
  134. {=================================================================}
  135. FUNCTION FlagIsSet (var flags; flagNum: word): boolean; assembler;
  136.  
  137. ASM
  138.     les     di, flags
  139.     mov     cx, flagNum
  140.     mov     bx, cx
  141.     shr     bx, 1
  142.     shr     bx, 1
  143.     shr     bx, 1
  144.     and     cl, 7
  145.     inc     cx
  146.     mov     al, es:[di][bx]
  147.     rol     al, cl
  148.     and     al, 1
  149. @done:
  150. END;
  151.  
  152. {=================================================================}
  153. FUNCTION NumFlagsSet (var flags; numFlags: word): word; assembler;
  154.  
  155. ASM
  156.     push    ds
  157.     cld
  158.     lds     si, flags
  159.     xor     bx, bx
  160.     mov     cx, numFlags
  161.     mov     dx, cx
  162.     xor     di, di
  163.     shr     cx, 1
  164.     shr     cx, 1
  165.     shr     cx, 1
  166.     jcxz    @remainder
  167. @byte8:
  168.     lodsb
  169.     shl     al, 1;  adc     bx, di
  170.     shl     al, 1;  adc     bx, di
  171.     shl     al, 1;  adc     bx, di
  172.     shl     al, 1;  adc     bx, di
  173.     shl     al, 1;  adc     bx, di
  174.     shl     al, 1;  adc     bx, di
  175.     shl     al, 1;  adc     bx, di
  176.     shl     al, 1;  adc     bx, di
  177.     loop    @byte8
  178. @remainder:
  179.     mov     cx, dx
  180.     and     cx, 7
  181.     jz      @done
  182.     lodsb
  183. @bit:
  184.     shl     al, 1
  185.     adc     bx, di
  186.     loop    @bit
  187. @done:
  188.     mov     ax, bx
  189.     pop     ds
  190. END;
  191.  
  192. {==================================================================}
  193. FUNCTION FlagString (var flags; numFlags: word): string; assembler;
  194.  
  195. { Returns a string of 0's & 1's showing the flags.  Note that at most 255
  196.   flags can shown in a string.  Returns nul if numFlags is 0 or greater
  197.   than 255. }
  198.  
  199. ASM
  200.     push    ds
  201.     cld
  202.     lds     si, flags
  203.     les     di, @result
  204.     mov     cx, numflags
  205.     or      ch, ch
  206.     jz      @ok
  207.     xor     cx, cx
  208. @ok:
  209.     mov     al, cl
  210.     stosb                   { length of string }
  211.     jcxz    @done
  212.     mov     dx, cx
  213.     push    dx              { save number of flags }
  214.     mov     ah, '0'
  215.     shr     dl, 1
  216.     shr     dl, 1
  217.     shr     dl, 1
  218.     jz      @remainder
  219. @byte8:                     { do 8 bits at a time }
  220.     lodsb
  221.     mov     bl, al
  222.     mov     cl, 8
  223. @bit8:
  224.     mov     al, ah          { ah = '0' }
  225.     shl     bl, 1
  226.     adc     al, dh          { dh = 0 }
  227.     stosb
  228.     loop    @bit8
  229.     dec     dl
  230.     jnz     @byte8
  231.  
  232. @remainder:                 { do remaining (numFlags mod 8) bits }
  233.     pop     dx
  234.     mov     cx, dx
  235.     and     cl, 7           { 0 <= cx <= 7 (number of flags in partial byte) }
  236.     jz      @done
  237.     lodsb                   { last byte containing flags  }
  238.     mov     bl, al
  239. @bit:
  240.     mov     al, ah          { ah = '0' }
  241.     shl     bl, 1
  242.     adc     al, dh          { dh = 0 }
  243.     stosb
  244.     loop    @bit
  245. @done:
  246.     pop     ds
  247. END;
  248.  
  249. {=============================================}
  250. CONSTRUCTOR oFlags.Init (numberOfFlags: word);
  251.  
  252. BEGIN
  253.     if numberOfFlags > 65520 then FAIL;
  254.     numFlags:= numberOfFlags;
  255.     GetMem (flags, (numFlags + 7) div 8);
  256.     if flags = nil then FAIL;
  257. END;
  258.  
  259. {==============================}
  260. PROCEDURE oFlags.ClearAllFlags;
  261.  
  262. BEGIN
  263.     FillChar (flags^, (numFlags + 7) div 8, #0);
  264. END;
  265.  
  266. {============================}
  267. PROCEDURE oFlags.SetAllFlags;
  268.  
  269. BEGIN
  270.     FillChar (flags^, (numFlags + 7) div 8, #1);
  271. END;
  272.  
  273. {========================================}
  274. PROCEDURE oFlags.SetFlag (flagNum: word);
  275.  
  276. BEGIN
  277.     DpFlags.SetFlag (flags^, flagNum);
  278. END;
  279.  
  280. {==========================================}
  281. PROCEDURE oFlags.ClearFlag (flagNum: word);
  282.  
  283. BEGIN
  284.     DpFlags.ClearFlag (flags^, flagNum);
  285. END;
  286.  
  287. {===========================================}
  288. PROCEDURE oFlags.ToggleFlag (flagNum: word);
  289.  
  290. BEGIN
  291.     DpFlags.ToggleFlag (flags^, flagNum);
  292. END;
  293.  
  294. {==================================================}
  295. FUNCTION oFlags.FlagIsSet (flagNum: word): boolean;
  296.  
  297. BEGIN
  298.     FlagIsSet:= DpFlags.FlagIsSet (flags^, flagNum);
  299. END;
  300.  
  301. {=================================}
  302. FUNCTION oFlags.NumFlagsSet: word;
  303.  
  304. BEGIN
  305.     NumFlagsSet:= DpFlags.NumFlagsSet (flags^, numFlags);
  306. END;
  307.  
  308. {==================================}
  309. FUNCTION oFlags.FlagString: string;
  310.  
  311. VAR
  312.     w : word;
  313.  
  314. BEGIN
  315.     w:= numFlags;
  316.     if w > 255 then w:= 255;
  317.     FlagString:= DpFlags.FlagString (flags^, w);
  318. END;
  319.  
  320. {======================}
  321. DESTRUCTOR oFlags.Done;
  322.  
  323. BEGIN
  324.     if flags <> nil then FreeMem (flags, (numFlags + 7) div 8);
  325. END;
  326.  
  327. END.        { Unit DpFlags }
  328.  
  329.